/* $RCSFile: CatManager.ascx.cs $
 * Apache license v2 2011 by Christian Surieux
 * $Source: ?/AddonNice.ECommerce/PageModules/ECommerce/CatManager.ascx.cs $
 * $log$
 * Revision 21 2010/08/09 11:08:12  christian.surieux
 *   Added Log comment to all .ascx .aspx .master files
 * Revision 8 2010/08/09 10:07:05  christian.surieux
 *   Added Log comment to all cs files
 */

using System;
using System.Diagnostics;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Web;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Globalization;

using AddonNice.Diagnostics;
using AddonNice.Security;
using AddonNice.Configuration;
using AddonNice.Helpers;
using AddonNice.UI;
using AddonNice.UI.WebControls;
using AddonNice.UI.DataTypes;
using AddonNice.Settings.ECommerce;
using AddonNice.Settings.Cache;

using AddonNice.CRMWrapper;

using AddonNice.ECommerce;
using AddonNice.ECommerce.UI;
using AddonNice.ECommerce.UI.WebControls;

using Telerik.Web.UI;

using Trace2    =   System.Diagnostics.Trace;

namespace AddonNice.PageModules.ECommerce
{
	/// <summary>
	///	Allow adding categories.
	/// </summary>
	public partial class CatManager : ECommerceModule 
	{
		private ProductsCRM ProductDB			=	new ProductsCRM();

		#region Global Implementation
        
        public override Guid GuidID 
		{
			get
			{
				return new Guid(EComStStr.ProductCatManGuid);
			}
		}

        public override bool DependsFromCustomCrmEntities
        {
            get{ return true;}
        }
        
        /// <summary>
        /// SortedList of entities/version from which this module depends, schema name is the key, version is a string in the form major.minor
        /// </summary>
        public override SortedList<string,string> RelatedCustomEntities
        {
            get
            {
                SortedList<string,string> Lst =   new SortedList<string,string>();
                Lst.Add(CrmStr.product,"1.0");
                return Lst;
            }
        }

        #endregion Global Implementation

        void CatManager_Load(object sender, EventArgs e)
        {
            if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CatManager CatManager_Load BEG isPostBack: {0}.",IsPostBack),ModuleTraceSwitch.Sw.Info);
            AddAjaxSetting(GridDock,CatTreeView);
            AddAjaxSetting(CatTreeView,CatTreeView);
            AddAjaxSetting(CatTreeView,ProdTreeView);
            AddAjaxSetting(ProdTreeView,ProdTreeView);
            RadGrid RadGrid2    =   (RadGrid)GridDock.ContentContainer.FindControl("RadGrid2");
            if (ModuleTraceSwitch.Sw.TraceVerbose)
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CatManager CatManager_Load RadGrid2 null: {0}.", RadGrid2 == null ),ModuleTraceSwitch.Sw.Info);
            if (RadGrid2 != null)
            {
                AddAjaxSetting(CatTreeView, RadGrid2);
            }
			if ( !IsPostBack ) 
			{
				BindCategories();
                BindProducts();
				// After up or down button when the page is refreshed, 
				// select the previously selected tab from the list.
                if (Request.Params["selectedCat"] != null) 
				{
					try
					{
                        string strTabIndex			= Request.Params["selectedCat"];
			            if (ModuleTraceSwitch.Sw.TraceVerbose)
                            Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CatManager CatManager_Load SelectCat: {0}",strTabIndex),ModuleTraceSwitch.Sw.Info);
						SelectCat(strTabIndex,CatTreeView.Nodes);
					}
					catch(Exception ex)
					{
			            if (ModuleTraceSwitch.Sw.TraceError)
                            Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CatManager CatManager_Load SelectCat ex: {0}",ex),ModuleTraceSwitch.Sw.Info);
                        // Not fatal throw;
					}
				}

			}
            if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine("[V]CatManager CatManager_Load END.",ModuleTraceSwitch.Sw.Info);
		}

        /// <summary>
		/// Given the CategoryID of a category, this function selects the right node in the category treeview
		/// </summary>
		private bool SelectCat(string strID,RadTreeNodeCollection Nodes)
		{
            if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CatManager SelectCat BEG strID: {0}, Nodes.Count: {1}.",strID,Nodes.Count),ModuleTraceSwitch.Sw.Info);
			foreach (RadTreeNode nd in Nodes)
			{
				if(nd.Value == strID)
				{
                    nd.Selected = true;
					SelectCat(nd);
					return true;
				}
                if ( nd.Nodes.Count > 0 && SelectCat(strID, nd.Nodes) )
                    return true;
			}
			return false;
		}

        /// <summary>
        /// Fills the RadGrid with information from selected node
        /// If no node, empties the grid
        /// </summary>
        protected void SelectCat(RadTreeNode selectedNode)
        {
            if ( selectedNode == null )
                return;
            if (ModuleTraceSwitch.Sw.TraceVerbose)
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CatManager SelectCat BEG Text:{0}, Selected: {1}", selectedNode.Text,selectedNode.Selected),ModuleTraceSwitch.Sw.Info);
            RadGrid RadGrid2    =   (RadGrid)GridDock.ContentContainer.FindControl("RadGrid2");
            if (ModuleTraceSwitch.Sw.TraceVerbose)
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CatManager SelectCat RadGrid2 null: {0}.", RadGrid2 == null ),ModuleTraceSwitch.Sw.Info);
            if ( RadGrid2 == null )
                return;
            selectedNode.Selected           =   true;
			DataTable InfoTb                =   new DataTable();
            const string colName            =   "Name";
            const string colDetail          =   "Detail";
			InfoTb.Columns.Add(colName, typeof(string));
			InfoTb.Columns.Add(colDetail, typeof(string));
            try
            {
                DataRow rw                  =   InfoTb.NewRow();
                rw[colName]                 =   LocalizeHelper.Localize("AM_NAME", "Name");
                string ntext                =   selectedNode.Text;
                rw[colDetail]               =   ntext;
                InfoTb.Rows.Add(rw);

                rw                          =   InfoTb.NewRow();
                rw[colName]                 =   "ID";
                rw[colDetail]               =   selectedNode.Value;
                InfoTb.Rows.Add(rw);
                if (ModuleTraceSwitch.Sw.TraceVerbose)
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CatManager SelectCat Selected Name: {0}, value: '{1}'.", 
                        selectedNode.Text,selectedNode.Value),ModuleTraceSwitch.Sw.Info);
                // Root we must exist
                if (int.Parse("0"+selectedNode.Value) != 0)
                {
                    SqlDataReader dr            =   null;
                    try
                    {
                        int catId               =   int.Parse(selectedNode.Value);
                        dr                      =   ProductDB.GetCategoryGlobalized(catId);
                        while (dr.Read())
                        {
                            int parentCatId     =   Convert.IsDBNull(dr[EComStStr.DBParentCategoryID]) ? 0 : (int)dr[EComStStr.DBParentCategoryID];
                            string parentCatName=   (string)dr[EComStStr.DBParentCategoryName];
                            bool hasSubCats     =   ((int)dr[EComStStr.DBNbSubCategories]) != 0;
                            if (ModuleTraceSwitch.Sw.TraceVerbose)
                                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CatManager SelectCat parentCatId: {0}, parentCatName: '{1}', hasSubCats: {2}.", 
                                    parentCatId,parentCatName,hasSubCats),ModuleTraceSwitch.Sw.Info);
                            rw                  =   InfoTb.NewRow();
                            rw[colName]          =   "Parent";
                            rw[colDetail]        =   (parentCatId == 0)? "Root":string.Format("{0}({1})",parentCatName,parentCatId);
                            InfoTb.Rows.Add(rw);

                            rw                  =   InfoTb.NewRow();
                            rw[colName]         =   LocalizeHelper.Localize(EComStStr.ResourceFile,EComStStr.ResourceItem,"CAT_MAN_HASSUBCATS", "Has sub categories");
                            rw[colDetail]       =   hasSubCats.ToString();
                            InfoTb.Rows.Add(rw);
                        }
                    }
                    catch (Exception ex)
                    {
                        if (ModuleTraceSwitch.Sw.TraceError)
                            Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CatManager SelectCat ex:{0}", ex),ModuleTraceSwitch.Sw.Info);
                        throw;
                    }
                    finally
                    {
                        if (dr != null)
                            dr.Close();
                    }
                }
            }
            catch (Exception ex)
            {
                if (ModuleTraceSwitch.Sw.TraceError)
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CatManager SelectCat Building ex:{0}", ex),ModuleTraceSwitch.Sw.Info);
                throw;
            }
            try
            {
                if (ModuleTraceSwitch.Sw.TraceVerbose)
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CatManager SelectCat Binding grid Records: {0}",InfoTb.Rows.Count),ModuleTraceSwitch.Sw.Info);
                RadGrid2.DataSource = InfoTb;
                RadGrid2.DataBind();
            }
            catch (Exception ex)
            {
                if (ModuleTraceSwitch.Sw.TraceError)
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CatManager SelectCat Binding ex:{0}", ex),ModuleTraceSwitch.Sw.Info);
                throw;
            }
            if (ModuleTraceSwitch.Sw.TraceVerbose)
                Trace2.WriteLine("[V]CatManager SelectCat END.",ModuleTraceSwitch.Sw.Info);
        }

        const string strProdMenu        =   "ProdMenu";
        const string strCatMenu         =   "CatMenu";

        /// <summary>
		/// Create the context menu for Products treeview
		/// </summary>
		RadTreeViewContextMenu CreateProdContextMenu()
		{

			RadTreeViewContextMenu cm	=   new RadTreeViewContextMenu();
			RadMenuItem cmi			    =	new RadMenuItem();
			cmi					        =	new RadMenuItem();
			cmi.Value			        =	"DeleteCatProd";
            cmi.ImageUrl                =   portalSettings.GetImageFromThemeSkins("DeleteBtn");
			cmi.Text			        =	LocalizeHelper.Localize(EComStStr.ResourceFile,EComStStr.ResourceItem,"CAT_MAN_DELCATPROD","Delete Category from product");
			cmi.PostBack		        =	true;
			cm.Items.Add(cmi);

            cmi                         =	new RadMenuItem();
			cmi.Value			        =	"Reset";
            cmi.ImageUrl                =   portalSettings.GetImageFromThemeSkins("EditBtn");
			cmi.Text			        =	LocalizeHelper.Localize(EComStStr.ResourceFile,EComStStr.ResourceItem,"CAT_MAN_RESETPROD","Reset Product");
			cmi.PostBack		        =	true;
			cm.Items.Add(cmi);
            return cm;
		}

        /// <summary>
		/// Handler for a right button menu click in ProdTreeView
		/// </summary>
        void ProdTreeView_ContextMenuItemClick(object o, RadTreeViewContextMenuEventArgs e)
        {
			string contextCommand = e.MenuItem.Value;
			
			RadTreeNode currentNode = e.Node;

			switch (contextCommand)
			{
				case "DeleteCatProd":          
					DeleteCatProd(currentNode);   
					break;
				case "Reset":    
					ResetCatProd(currentNode);
					break;
			}
		}

        /// <summary>
        /// Remove a category from a product
        /// </summary>
        void DeleteCatProd(RadTreeNode nd)
        {
            int CategoryID          =   int.Parse(nd.Value);
            RadTreeNode prodNd      =   nd.ParentNode;
            Guid ProductId          =   new Guid(prodNd.Value);
            try
            {
                ProductDB.DeleteProductCategory(ProductId,CategoryID);
            }
			catch(Exception ex)
			{
                if ( ModuleTraceSwitch.Sw.TraceError )
    				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CatManager DeleteCatProd ex: {0}",ex),ModuleTraceSwitch.Sw.Info);
                throw;
			}
            RadTreeNode ndP     =   nd.ParentNode;
			nd.Owner.Nodes.Remove(nd); 
            if (ModuleTraceSwitch.Sw.TraceVerbose)
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CatManager DeleteCatProd ProductId: {0}, CategoryId: {1}",ProductId,CategoryID),ModuleTraceSwitch.Sw.Info);
        }

        /// <summary>
        /// Remove all category from a product
        /// </summary>
        void ResetCatProd(RadTreeNode nd)
        {
            if ( ModuleTraceSwitch.Sw.TraceVerbose)
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CatManager ResetCatProd BEG Node: {0}",nd.Text),ModuleTraceSwitch.Sw.Info);
            RadTreeNode prodNd      =   nd;
            if ( (nd.Category != "Product") && (nd.ParentNode != null) )
                prodNd              =   nd.ParentNode;
            if ( ModuleTraceSwitch.Sw.TraceVerbose)
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CatManager ResetCatProd prodNd: {0}",prodNd.Text),ModuleTraceSwitch.Sw.Info);
            Guid ProductId          =   new Guid(prodNd.Value);
            try
            {
                ProductDB.DeleteAllProductCategory(ProductId);
            }
			catch(Exception ex)
			{
                if ( ModuleTraceSwitch.Sw.TraceError )
    				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CatManager ResetCatProd ex: {0}",ex),ModuleTraceSwitch.Sw.Info);
                throw;
			}
			prodNd.Nodes.Clear(); 
            if (ModuleTraceSwitch.Sw.TraceVerbose)
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CatManager ResetCatProd  END ProductId: {0}",ProductId),ModuleTraceSwitch.Sw.Info);
        }

        /// <summary>
		/// Create the context menu for Categories treeview
		/// </summary>
		RadTreeViewContextMenu CreateCatContextMenu()
		{

			RadTreeViewContextMenu cm	=   new RadTreeViewContextMenu();
            cm.ID                       =   strCatMenu;

			RadMenuItem cmi			    =	new RadMenuItem();
			cmi.Value			        =	"AddCat";
            cmi.ImageUrl                =   portalSettings.GetImageFromThemeSkins("AddPage");
			cmi.Text			        =	LocalizeHelper.Localize(EComStStr.ResourceFile,EComStStr.ResourceItem,"CAT_MAN_ADDCAT","Add Category");
			cmi.PostBack		        =	true;
			cm.Items.Add(cmi);

			cmi					        =	new RadMenuItem();
			cmi.Value			        =	"DeleteCat";
            cmi.ImageUrl                =   portalSettings.GetImageFromThemeSkins("DeleteBtn");
			cmi.Text			        =	LocalizeHelper.Localize(EComStStr.ResourceFile,EComStStr.ResourceItem,"CAT_MAN_DELCAT","Delete Category");
			cmi.PostBack		        =	true;
			cm.Items.Add(cmi);

            cmi                         =	new RadMenuItem();
			cmi.Value		            =	"EditCat";
            cmi.ImageUrl                =   portalSettings.GetImageFromThemeSkins("EditBtn");
			cmi.Text			        =	LocalizeHelper.Localize(EComStStr.ResourceFile,EComStStr.ResourceItem,"CAT_MAN_EDITCAT","Edit Category");
			cmi.PostBack		        =	true;
			cm.Items.Add(cmi);
            return cm;
		}

        /// <summary>
		/// Handler for a right button menu click in CatTreeView
		/// </summary>
        void CatTreeView_ContextMenuItemClick(object o, RadTreeViewContextMenuEventArgs e)
        {
			string contextCommand = e.MenuItem.Value;
			
			RadTreeNode currentNode = e.Node;

			switch (contextCommand)
			{
				case "DeleteCat":          
					DeleteCat( currentNode);   
					break;
				case "EditCat":    
					EditCat(currentNode);
					break;
				case "AddCat":
					AddCat(currentNode);
					break;
			}
		}

        /// <summary>
        /// Edit category: TBD
        /// </summary>
        void EditCat(RadTreeNode nd)
        {
        }

        void ResetPageSettings()
        {
            // Reset all pages settings cache using the key prefix
            string wkey                         =   Key.TabSettings(0).TrimEnd(new char[] { '0' });
            CurrentCache.RemoveAll(wkey);
        }

        /// <summary>
        /// Add a new category
        /// </summary>
        void AddCat(RadTreeNode nd)
        {
            int parentCategoryID    =   (nd == CatTreeView.Nodes[0]) ? 0:int.Parse(nd.Value);
            const string strNewCat  =   "New Category";
            string details          =   string.Empty;
            int newCatId            =   -1;
            try
            {
                if ( ModuleTraceSwitch.Sw.TraceVerbose )
				    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CatManager AddCat catId: {0}, newName: '{1}', Detail: '{2}', parentId: {3}",
                        new object[]{newCatId,strNewCat,details,parentCategoryID}),ModuleTraceSwitch.Sw.Info);
                newCatId            =   ProductDB.AddCategoryGlobalized(strNewCat,details,parentCategoryID,PortalID);
            }
			catch(Exception ex)
			{
                if ( ModuleTraceSwitch.Sw.TraceError )
    				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CatManager AddCat ex: {0}",ex),ModuleTraceSwitch.Sw.Info);
                throw;
			}
            RadTreeNode newnd       =   new RadTreeNode(strNewCat, newCatId.ToString());
            nd.ContextMenuID        =   strCatMenu;
            nd.Attributes["Detail"] =   details;
            nd.Category             =   "Cat";
            nd.Nodes.Add(newnd);
            ResetPageSettings();
            // Reset all pages settings cache using the key prefix
            if (ModuleTraceSwitch.Sw.TraceVerbose)
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CatManager AddCat Added NewCatId: {0}, nd: {1}", newCatId,nd.Value),ModuleTraceSwitch.Sw.Info);
        }

        /// <summary>
        /// Delete a category
        /// </summary>
        void DeleteCat(RadTreeNode nd)
        {
            int CategoryID          =   int.Parse(nd.Value);
            try
            {
                ProductDB.DeleteCat(CategoryID);
            }
			catch(Exception ex)
			{
                if ( ModuleTraceSwitch.Sw.TraceError )
    				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CatManager DeleteCat ex: {0}",ex),ModuleTraceSwitch.Sw.Info);
                throw;
			}
            RadTreeNode ndP     =   nd.ParentNode;
			nd.Owner.Nodes.Remove(nd); 
            SelectCat(ndP);
            ResetPageSettings();
            if (ModuleTraceSwitch.Sw.TraceVerbose)
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CatManager DeleteCat CategoryId: {0}", CategoryID),ModuleTraceSwitch.Sw.Info);
        }

        /// <summary>
        /// Read all products from CRM and insert them as root nodes in treeView
        /// </summary>
        void BindProducts()
		{
            if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine("[V]CatManager BindProducts BEG.",ModuleTraceSwitch.Sw.Info);
            // insert context menu
            ProdTreeView.ContextMenus.Add(CreateProdContextMenu());
			try
			{
				DataTable tbProd			=	new ProductsCRM().GetAllProducts();
				ProdTreeView.DataSource		=	tbProd;
                ProdTreeView.DataTextField  =   CrmStr.name; 
                ProdTreeView.DataValueField =   CrmStr.productid;
				ProdTreeView.DataBind();
			}
			catch(Exception ex)
			{
                if ( ModuleTraceSwitch.Sw.TraceError )
				    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CatManager BindProducts ex: {0}",ex),ModuleTraceSwitch.Sw.Info);
                throw;
			}
            if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine("[V]CatManager BindProducts END.",ModuleTraceSwitch.Sw.Info);
		}

		/// <summary>
		/// Read all categories from DB and insert them in treeview
		/// </summary>
        void BindCategories()
		{
            if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine("[V]CatManager BindCategories BEG.",ModuleTraceSwitch.Sw.Info);
            // insert context menu
            CatTreeView.ContextMenus.Add(CreateCatContextMenu());
			// Read list of categories
			SqlDataReader drCategory			=	null;
			try
			{
				drCategory						=	ProductDB.GetAllCategoriesGlobalized(PortalID);
				CatTreeView.DataSource			=	drCategory;
                RadTreeNode rootNode            =   new RadTreeNode("Categories","0");
                rootNode.Category               =   "Root";
                CatTreeView.Nodes.Add(rootNode);
                while (drCategory.Read())
                {
                    RadTreeNode node            = new RadTreeNode((string)drCategory[EComStStr.DBCategoryName],((int)drCategory[EComStStr.DBCategoryID]).ToString());
                    node.Category               =   "Cat";
                    node.Attributes["Detail"]   =   drCategory[EComStStr.DBCategoryDetail].ToString();

                    int ParentId        =   (drCategory[EComStStr.DBParentCategoryID] == DBNull.Value) ? 0:(int)drCategory[EComStStr.DBParentCategoryID];
                    RadTreeNode parentNd    =   (ParentId == 0 ) ? rootNode:CatTreeView.FindNodeByValue(ParentId.ToString());
                    if ( parentNd != null )
                        parentNd.Nodes.Add(node);
                }
                CatTreeView.ExpandAllNodes();
			}
			catch(Exception ex)
			{
                if ( ModuleTraceSwitch.Sw.TraceError )
    				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CatManager BindCategories ex: {0}",ex),ModuleTraceSwitch.Sw.Info);
                throw;
			}
			finally
			{
                if ( drCategory != null )
				    drCategory.Close();
			}
            if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CatManager BindCategories Nodes.Count: {0}",CatTreeView.Nodes.Count),ModuleTraceSwitch.Sw.Info);
		}

        /// <summary>
        /// For each Crm product we get the associated categories and attach them as sub trees
        /// </summary>
        void ProdTreeView_NodeDataBound(object sender, RadTreeNodeEventArgs e)
        {
            if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CatManager ProdTreeView_NodeDataBound BEG Node.Value: '{0}', Node.Text: '{1}'",
                    e.Node.Value,e.Node.Text),ModuleTraceSwitch.Sw.Info);
            // Set the 'node category'
            e.Node.Category     =   "product";
            
            string strProd      =   e.Node.Value;
            if (string.IsNullOrEmpty(strProd))
            {
                DataRowView drv =   (DataRowView)e.Node.DataItem;
                if (drv != null)
                    e.Node.Value    =   drv[CrmStr.productid].ToString();
            if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CatManager ProdTreeView_NodeDataBound extracted from datarowview Node.Value: '{0}', Node.Text: '{1}'",
                    e.Node.Value,e.Node.Text),ModuleTraceSwitch.Sw.Info);
            }
            if (string.IsNullOrEmpty(strProd))
            {
                if ( ModuleTraceSwitch.Sw.TraceVerbose )
				    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CatManager ProdTreeView_NodeDataBound no value Skipping Node: '{0}'",
                        e.Node.Text),ModuleTraceSwitch.Sw.Info);
                return;
            }
            Guid prodId                 =   new Guid(strProd);
            SqlDataReader dr            =   null;
            // First get list of associated categories
            try
            {
                dr                      =   ProductDB.GetProductCatsListGlobalized(prodId);
                while(dr.Read() )
                {
                    int CatId           =   (int)dr["CategoryID"];
                    string CategoryName =   (string)dr["CategoryName"];
                    RadTreeNode nd      =   new RadTreeNode(CategoryName,CatId.ToString());
                    nd.Category         =   "Cat";
                    e.Node.Nodes.Add(nd);
                }
            }
			catch(Exception ex)
			{
                if ( ModuleTraceSwitch.Sw.TraceError )
    				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CatManager ProdTreeView_NodeDataBound ex: {0}",ex),ModuleTraceSwitch.Sw.Info);
                throw;
			}
			finally
			{
                if ( dr != null )
				    dr.Close();
			}
            if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CatManager ProdTreeView_NodeDataBound END Count: {0}",CatTreeView.Nodes.Count),ModuleTraceSwitch.Sw.Info);
        }

        /// <summary>
        /// Change the categoryName
        /// </summary>
        void CatTreeView_NodeEdit(object sender, RadTreeNodeEditEventArgs e)
        {
            if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine("[V]CatManager CatTreeView_NodeEdit BEG.",ModuleTraceSwitch.Sw.Info);
            string oldName  =   e.Node.Text;
            string newName  =   e.Text;
            string Detail   =   e.Node.Attributes["Detail"];
            int catId       =   int.Parse(e.Node.Value);
            int parentId    =   int.Parse(e.Node.ParentNode.Value);
            try
            {
                if ( ModuleTraceSwitch.Sw.TraceVerbose )
				    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CatManager CatTreeView_NodeEdit catId: {0}, newName: '{1}', Detail: '{2}', parentId: {3}",
                        new object[]{catId,newName,Detail,parentId}),ModuleTraceSwitch.Sw.Info);
                ProductDB.UpdateCatGlobalized(catId,newName,Detail,parentId);
                e.Node.Text =   newName;
                SelectCat(e.Node);
            }
			catch(Exception ex)
			{
                if ( ModuleTraceSwitch.Sw.TraceError )
    				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CatManager CatTreeView_NodeEdit ex: {0}",ex),ModuleTraceSwitch.Sw.Info);
                throw;
			}
        }

		void CatTreeView_NodeClick(object o, RadTreeNodeEventArgs e)
		{
            if (ModuleTraceSwitch.Sw.TraceVerbose)
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CatManager CatTreeView_NodeClick BEG Text:{0}, Selected: {1}", e.Node.Text,e.Node.Selected),ModuleTraceSwitch.Sw.Info);
	        SelectCat(e.Node);
            if (ModuleTraceSwitch.Sw.TraceVerbose)
                Trace2.WriteLine("[V]CatManager CatTreeView_NodeClick END.",ModuleTraceSwitch.Sw.Info);
        }
        /// <summary>
        /// We drop categories on products to add them to the product
        /// </summary>
        void CatTreeView_NodeDrop(object sender, RadTreeNodeDragDropEventArgs e)
        {
            if (ModuleTraceSwitch.Sw.TraceVerbose)
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CatManager CatTreeView_NodeDrop BEG SourceDragNode:{0}, DestDragNode: {1}", 
                    e.SourceDragNode.Text,e.DestDragNode.Text),ModuleTraceSwitch.Sw.Info);
            // Fetch event data 
            RadTreeNode sourceNode		= e.SourceDragNode;
            RadTreeNode destNode		= e.DestDragNode;
    
            // node may have been dropped outside treeviews, or on itself
			// We don't accept inversing hierarchy
			if (destNode == null || sourceNode.Equals(destNode) || sourceNode.IsAncestorOf(destNode) )
				return;
			RadTreeViewDropPosition d	=	e.DropPosition;
			try
			{
                // First case: moving nodes inside catTreeview
                if (destNode.TreeView == CatTreeView)
                {
                    // don't accept reverse move
                    if (sourceNode.TreeView != CatTreeView )
                        return;
				    bool changeParent       =   (destNode.ParentNode != sourceNode.ParentNode );
				    switch (d)
				    {
					    case RadTreeViewDropPosition.Above:
						    sourceNode.Owner.Nodes.Remove(sourceNode);
						    destNode.InsertBefore(sourceNode);
						    if (ModuleTraceSwitch.Sw.TraceVerbose)
                                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CatManager CatTreeView_NodeDrop: {0} changeParent: {1}", sourceNode.Text, changeParent),ModuleTraceSwitch.Sw.Info);
						    if (changeParent)
							    ChangeParentCat(sourceNode, destNode.ParentNode);
						    break;
					    case RadTreeViewDropPosition.Below:
						    sourceNode.Owner.Nodes.Remove(sourceNode);
						    destNode.InsertAfter(sourceNode);
						    if (ModuleTraceSwitch.Sw.TraceVerbose)
                                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CatManager CatTreeView_NodeDrop: {0} changeParent: {1}", sourceNode.Text, changeParent),ModuleTraceSwitch.Sw.Info);
						    if (changeParent)
							    ChangeParentCat(sourceNode, destNode.ParentNode);
						    break;
					    case RadTreeViewDropPosition.Over:
                            // different rules here
				            if (destNode.ParentNode == sourceNode.ParentNode )
                                changeParent       =   true;
				            else if (destNode == sourceNode.ParentNode )
                                changeParent       =   false;
						    if (ModuleTraceSwitch.Sw.TraceVerbose)
                                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CatManager CatTreeView_NodeDrop: {0} changeParent: {1}", sourceNode.Text, changeParent),ModuleTraceSwitch.Sw.Info);
						    sourceNode.Owner.Nodes.Remove(sourceNode);
						    destNode.Nodes.Add(sourceNode);
						    if (changeParent)
							    ChangeParentCat(sourceNode, destNode);
						    break;
					    default:
						    return;
				    }
				    // Expand destination node to see result of swap immediately.
				    destNode.ExpandChildNodes();
			    }
                // second case: moving nodes from catTreeview to ProdTreeview
                // we do a copy of source node under the semected product
                else if (destNode.TreeView == ProdTreeView)
                {
                    // don't accept move inside prodTreeview
                    if (sourceNode.TreeView != CatTreeView )
                        return;
                    if ( destNode.Category == "Cat" )
                        destNode    =   destNode.ParentNode;
                    RadTreeNode nd      =   new RadTreeNode(sourceNode.Text,sourceNode.Value);
                    nd.Category         =   "Cat";
                    destNode.Nodes.Add(nd);
                    Guid productID      =   new Guid(destNode.Value);
                    int CatId           =   int.Parse(sourceNode.Value);
                    if ( ModuleTraceSwitch.Sw.TraceVerbose )
				        Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CatManager CatTreeView_NodeDrop productID: {0}, CatId: {1}",productID,CatId),ModuleTraceSwitch.Sw.Info);
                    ProductDB.AddProductCategory(productID,CatId,string.Empty);
				    // Expand destination node to see result of swap immediately.
				    ProdTreeView.ExpandAllNodes();
			    }
            }
			catch (Exception ex)
			{
				if (ModuleTraceSwitch.Sw.TraceError)
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CatManager CatTreeView_NodeDrop ex:{0}", ex),ModuleTraceSwitch.Sw.Info);
                throw;
			}
        }

		void ChangeParentCat(RadTreeNode sourceNode, RadTreeNode destNode)
		{
			try
			{
				if (ModuleTraceSwitch.Sw.TraceVerbose)
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CatManager ChangeParentCat {0} to {1}",sourceNode.Text,destNode.Text),ModuleTraceSwitch.Sw.Info);
				int catId		= int.Parse(sourceNode.Value);
				int parentId	= int.Parse(destNode.Value);
				// write to database
                if ( ModuleTraceSwitch.Sw.TraceVerbose )
				    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CatManager ChangeParentCat catId: {0}, parentId: {1}",
                        catId,parentId),ModuleTraceSwitch.Sw.Info);
				ProductDB.UpdateCategoryParent(catId, parentId);
			}
			catch (Exception ex)
			{
				if (ModuleTraceSwitch.Sw.TraceError)
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CatManager ChangeParentCat ex: {0}",ex),ModuleTraceSwitch.Sw.Info);
				throw;
			}
		}

        void GridDock_Command(object sender, DockCommandEventArgs e)
        {
            if (ModuleTraceSwitch.Sw.TraceVerbose)
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CatManager GridDock_Command name: {0}.", e.Command.Name),ModuleTraceSwitch.Sw.Info);
            RadTreeNode nd      = CatTreeView.SelectedNode;
            if ( nd == null )
                return;
            switch (e.Command.Name)
            {
                case "EditCat":
					EditCat(nd);
                    break;
                case "DeleteCat":
					DeleteCat(nd);   
                    break;
                case "addCat":
                    AddCat(nd);
                    break;
            }
        }

        #region Dock management

        const string pgCookieName   =   "AddonNice_ECatManager";
        
        protected override string DockWindowCookieName
        {
            get
            {
                return pgCookieName;
            }
        }

        protected override RadDockLayout DockWindowLayout
        {
            get
            {
                return RadDockLayout1;
            }
        }
        #endregion Dock management

        #region Std Overrides

		override protected void OnInit(EventArgs e)
		{
			InitializeComponent();
			base.OnInit(e);
		}
		
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
            Load                                +=  new EventHandler(CatManager_Load);
            CatTreeView.NodeDrop                +=  new RadTreeViewDragDropEventHandler(CatTreeView_NodeDrop);
            CatTreeView.NodeEdit                +=  new RadTreeViewEditEventHandler(CatTreeView_NodeEdit);
            CatTreeView.ContextMenuItemClick    +=  new RadTreeViewContextMenuEventHandler(CatTreeView_ContextMenuItemClick);
            CatTreeView.NodeClick               +=  new RadTreeViewEventHandler(CatTreeView_NodeClick);
            ProdTreeView.NodeDataBound          +=  new RadTreeViewEventHandler(ProdTreeView_NodeDataBound);
            ProdTreeView.ContextMenuItemClick   +=  new RadTreeViewContextMenuEventHandler(ProdTreeView_ContextMenuItemClick);
            GridDock.Command                    +=  new DockCommandEventHandler(GridDock_Command);
            RadDockLayout1.LoadDockLayout       +=  new DockLayoutEventHandler(DockWindowLayout_LoadDockLayout);
            RadDockLayout1.SaveDockLayout       +=  new DockLayoutEventHandler(DockWindowLayout_SaveDockLayout);
		}

		#endregion
	}
}
